/*
 *  Filename:lsv_log.h
 *  Description:
 *
 *  Created on: 2017年3月2日
 *  Author: Asdf(825674301)
 */

#ifndef __LSV_LOG_H_
#define __LSV_LOG_H_

#include "lsv_conf.h"
#include "lsv_types.h"
#include "lsv_volume_proto.h"
#include "lsv_bitmap.h"



/*===define a log===*/
/*log layout size*/
#define LSV_LOG_PAGE_NUM (LSV_CHUNK_SIZE/LSV_PAGE_SIZE-1)    // 255

#define LSV_LOG_HEAD_AREA (16)
#define LSV_LOG_HLOG_SIZE (16)
#define LSV_LOG_HLOG_AREA (LSV_LOG_HLOG_SIZE*LSV_LOG_PAGE_NUM)
#define LSV_LOG_SLOG_SIZE (LSV_PAGE_SIZE)
#define LSV_LOG_SLOG_AREA (LSV_LOG_SLOG_SIZE*LSV_LOG_PAGE_NUM)

/*log layout offset*/
#define LSV_LOG_HEAD (0)
#define LSV_LOG_HLOG (LSV_LOG_HEAD+LSV_LOG_HEAD_AREA)
#define LSV_LOG_SLOG (LSV_LOG_HLOG+LSV_LOG_HLOG_AREA)

#pragma pack(8)

typedef struct _lsv_log_head {
        uint64_t timestamp;
        uint32_t page_count;   // [0, 255]
        uint32_t crc;
} lsv_log_head_t;

typedef struct _lsv_log_hlog {
        uint64_t lba;
        uint32_t snap_id;
        uint32_t crc;
} lsv_log_hlog_t;

typedef struct _lsv_log_slog {
        lsv_u8_t page[LSV_PAGE_SIZE];
} lsv_log_slog_t;

#pragma pack()

typedef struct _lsv_log_proto {
        void* log; //log data
        lsv_log_head_t *head;
        lsv_log_hlog_t *hlog; //array
        lsv_log_slog_t *slog; //array
        uint32_t chunk_id;
} lsv_log_proto_t;

#define lsv_log_proto_link(log_ptoto) do{\
        (log_ptoto)->head = (log_ptoto)->log + LSV_LOG_HEAD;\
        (log_ptoto)->hlog = (log_ptoto)->log + LSV_LOG_HLOG;\
        (log_ptoto)->slog = (log_ptoto)->log + LSV_LOG_SLOG;\
}while(0);

#define lsv_log_proto_unlink(log_ptoto) do{\
        (log_ptoto)->head = NULL;\
        (log_ptoto)->hlog = NULL;\
        (log_ptoto)->slog = NULL;\
}while(0);

/*===end define a log===*/

// submodule: gc

#include "lsv_gc.h"

#define LOG_TEMP_LOCK (0)

typedef struct _lsv_log_info {
        lsv_gc_context_t *gc_context;
#if LOG_TEMP_LOCK
        lsv_rwlock_t log_temp_rwlock;
#endif
} lsv_log_info_t;

int lsv_log_init(lsv_volume_proto_t *lsv_info, lsv_u32_t flag);

int lsv_log_destroy(lsv_volume_proto_t* lsv_info);

int lsv_log_flush(lsv_volume_proto_t* lsv_info);


/**
 * @brief write log, if flush, < 1M?
 *
 * @param lsv_info
 * @param log
 * @return
 */
int lsv_log_write(lsv_volume_proto_t *lsv_info, void* log);

/**
 *
 * @param lsv_info
 * @param chunk_id
 * @param buf
 * @return
 */
int lsv_log_read(lsv_volume_proto_t *lsv_info, uint32_t chunk_id, lsv_s8_t *buf);

int lsv_log_check(uint32_t chunk_id, lsv_s8_t *buf);

int lsv_log_setattr(lsv_volume_proto_t *lsv_info);

//=========check and statistics========//

int lsv_log_check_by_bitmap(lsv_volume_proto_t *lsv_info);

#endif /* __LSV_LOG_H_ */
